package com.fcscs.cservice.client.common;

import java.util.Date;

import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.util.DateWrapper;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.form.Time;
import com.extjs.gxt.ui.client.widget.form.TimeField;

/**
 * Provides a time field with enhanced date handling capabilities
 * 
 * <p>
 * e.g. typical usage of a separated date and time input field which belong together
 * </br></br>
 * <code>
 *	final ExtTimeField timeField=new ExtTimeField();</br>
 *	
 *	final DateField dateField=new DateField();</br>
 *
 *	</br>	
 *	Button timeTestButton = new Button("Time Resolving");</br>
 *	timeTestButton.addSelectionListener(new SelectionListener<ComponentEvent>(){</br>
 *		public void componentSelected(ComponentEvent ce) {</br>
 *			System.out.println(timeField.getDateTimeValue(dateField.getValue()));</br>
 *		}});</br>
 *
 * </code>
 *
 * </p>
 */
public class ExtTimeField extends TimeField {

	private Date date;

	public ExtTimeField() {
		this(null);
	}

	public ExtTimeField(Date date) {
//		setForceSelection(true);
		setValue(date);
	}

	public void setValue(Date dateValue) {
		if (dateValue != null) {
			date = new Date();
			date.setTime(dateValue.getTime());
			Time timeAsModelData = new Time();
			timeAsModelData.set("text", getFormat().format(date));
			setValue(timeAsModelData);
		} else {
			date=null;
		}
	}

	/**
	 * Returns a {@link Date} instance with time value set
	 * 
	 * @param forDate
	 *            date value for which the time will be set
	 * @return {@link Date} instance with time set when time is selected
	 *         otherwise date with no time information
	 */
	public Date getDateTimeValue(Date forDate) {

		Date resultDate = null;

		String timeAsString = resolveTimeAsString();

		if (timeAsString != null && timeAsString.length() > 0) {
			Date selectedTime=null;
			
			selectedTime = parseDateFromString(timeAsString);

			// check if time shoult be set for an existing date instance
			if (forDate == null) {
				// no existing date instance -> therefore result is
				// parsed date
				resultDate = selectedTime;
			} else {
				DateWrapper selectedTimeWrapper = new DateWrapper(selectedTime);

				// set selected time value for date
				resultDate = new DateWrapper(forDate).clearTime().addHours(selectedTimeWrapper.getHours()).addMinutes(
						selectedTimeWrapper.getMinutes()).asDate();
			}

		} else {
			// in case of no selection -> return current date without time
			// information
			resultDate = new DateWrapper(forDate!=null?forDate:new Date()).clearTime().asDate();
		}
		return resultDate;
	}

	/**
	 * 
	 * @param timeAsString
	 * @param selectedTime
	 * @return date instance from time string
	 */
	@SuppressWarnings("unchecked")
	protected Date parseDateFromString(String timeAsString) {
		Date selectedTime =null;
		try {
			// parse Date instance for time string
			selectedTime = getFormat().parse(timeAsString);
		} catch (IllegalArgumentException iae) {
			// in case of parsing error 
			@SuppressWarnings("rawtypes")
			final Listener l = new Listener<ComponentEvent>() {
			      public void handleEvent(ComponentEvent ce) {
						markInvalid(messages.getInvalidText());
						focus();						

			      }
			    };
			MessageBox.alert("", messages.getInvalidText(),l);
		}
		return selectedTime;
	}

	protected String resolveTimeAsString() {
		String timeAsString = null;
		if (getForceSelection()) {
			if (getSelection().size() != 0) {
				ModelData selectedTimeAsModelData = getSelection().get(0);
				// check selection of time info
				if (selectedTimeAsModelData != null) {
					// resolve time info as string
					timeAsString = selectedTimeAsModelData.get("text");
				}
			}
		} else {
			timeAsString=getRawValue();
		}
		return timeAsString;
	}

	public Date getDateTimeValue() {
		return getDateTimeValue(date);
	}

}
